package com.google.code.jholidays.events.parameters;

import java.util.Calendar;

import com.google.code.jholidays.events.FloatingEvent;

/**
 * Stores information which is used by {@link FloatingEvent} during its date
 * calculation.
 * <p>
 * <tt>DayOfWeek</tt> index, <tt>Month</tt> index and <tt>Order</tt> index are
 * stored.
 * <p>
 * DayOfWeek index is between 0 and 6. First day of week is locale dependent.
 * Month index is between 0 and 11. Zero stands for January, 1 for February and
 * so on.
 * <p>
 * Order index is normally between 1 and 4. But month can have 5 Tuesdays or 5
 * Fridays in month for example, so order for those days of week can be between
 * 1 and L. <b>L</b> char in this case means "Last" (e.g last sunday, last
 * monday and so on)
 * <p>
 * DayOfWeek and Month indexes verification process heavily depends on
 * {@link Calendar} methods: <tt>getActualMinimum(Calendar.DAY_OF_WEEK)</tt>,
 * <tt>getActualMinimum(Calendar.MONTH)</tt> and their maximum analogs
 * 
 * 
 * @author tillias
 * 
 */
public class DateParameters {

    /**
     * Creates new instance of date parameters and verifies all indexes.
     * 
     * @param dayOfWeek
     *            Day of week index
     * @param month
     *            Month index
     * @param order
     *            Order index
     * @throws IllegalArgumentException
     *             Thrown if any index passed to constructor is invalid (e.g.
     *             out of valid range)
     */
    public DateParameters(int dayOfWeek, int month, DayOfWeekOrder order) {
	if (!verifyMonth(month))
	    throw new IllegalArgumentException("Invalid month");
	if (!verifyDayOfWeek(dayOfWeek))
	    throw new IllegalArgumentException("Invalid day of week");

	this.dayOfWeek = dayOfWeek;
	this.month = month;
	this.order = order;
    }

    /**
     * Gets day of week index
     * 
     * @return Day of week index.
     */
    public int getDayOfWeek() {
	return dayOfWeek;
    }

    /**
     * Gets month index
     * 
     * @return Month index
     */
    public int getMonth() {
	return month;
    }

    /**
     * Gets order index of day of week in month
     * 
     * @return Order index of day of week in month
     */
    public DayOfWeekOrder getOrder() {
	return order;
    }

    private boolean verifyMonth(int v_month) {
	boolean result = false;

	Calendar calendar = Calendar.getInstance();
	int min = calendar.getActualMinimum(Calendar.MONTH);
	int max = calendar.getActualMaximum(Calendar.MONTH);
	if (v_month <= max && v_month >= min) {
	    result = true;
	}

	return result;
    }

    private boolean verifyDayOfWeek(int v_dayOfWeek) {
	boolean result = false;

	Calendar calendar = Calendar.getInstance();

	int min = calendar.getActualMinimum(Calendar.DAY_OF_WEEK);
	int max = calendar.getActualMaximum(Calendar.DAY_OF_WEEK);
	if (v_dayOfWeek <= max && v_dayOfWeek >= min) {
	    result = true;
	}

	return result;
    }

    int dayOfWeek;
    int month;
    DayOfWeekOrder order;
}
